#ifndef EPUBDUKPT_CONTEXT_PARAMS1_HPP
#define EPUBDUKPT_CONTEXT_PARAMS1_HPP

class EpubContextParams1 : public EpubContextParams0 {
public:
  constexpr static int BLOCK_SIZE = 16;

  EpubContextParams1()
      : EpubContextParams0(), mComponentA(), mComponentB(), mComponentC(), mBDK() {}

  void setBDK(unsigned char const *in, int inLen) {
    mBDK.resize(inLen);
    memcpy(&mBDK[0], in, inLen);
  }

  void setComponentA(unsigned char const *in, int inLen) {
    mComponentA.resize(inLen);
    memcpy(&mComponentA[0], in, inLen);
  }

  void setComponentB(unsigned char const *in, int inLen) {
    mComponentB.resize(inLen);
    memcpy(&mComponentB[0], in, inLen);
  }

  void setComponentC(unsigned char const *in, int inLen) {
    mComponentC.resize(inLen);
    memcpy(&mComponentC[0], in, inLen);
  }

  void clean() {
    mComponentA.clear();
    mComponentB.clear();
    mComponentC.clear();
    mBDK.clear();
  }

  auto bdk() -> std::vector<unsigned char> & {
    if (!mBDK.empty())
      return mBDK;
    if (mComponentA.empty() || mComponentB.empty())
      return mBDK;

    mBDK.resize(BLOCK_SIZE);
    for (int i = 0; i < BLOCK_SIZE; ++i)
      mBDK[i] = mComponentA[i] ^ mComponentB[i];

    if (!mComponentC.empty()) {
      for (int i = 0; i < BLOCK_SIZE; ++i)
        mBDK[i] ^= mComponentC[i];
    }

    return mBDK;
  }

private:
  std::vector<unsigned char> mComponentA;
  std::vector<unsigned char> mComponentB;
  std::vector<unsigned char> mComponentC;

  std::vector<unsigned char> mBDK;
};

#endif//EPUBDUKPT_CONTEXT_PARAMS1_HPP
